using System;
using Microsoft.SPOT;

namespace nRF24L10P.Helper
{

        public static class BitHelper
        {
            /// <summary>
            /// 1000_0000
            /// </summary>
            public  const byte B7 = 0x80; 
            /// <summary>
            /// 0100_0000
            /// </summary>
            public  const byte B6 = 0x40;

            /// <summary>
            /// 0010_0000
            /// </summary>
            public  const byte B5 = 0x20;

            /// <summary>
            /// 0001_0000
            /// </summary>
            public  const byte B4 = 0x10;

            /// <summary>
            /// 0000_1000
            /// </summary>
            public  const byte B3 = 0x08;

            /// <summary>
            /// 0000_0100
            /// </summary>
            public  const byte B2 = 0x04;

            /// <summary>
            /// 0000_0010
            /// </summary>
            public  const byte B1 = 0x02;

            /// <summary>
            /// 0000_0001
            /// </summary>
            public  const byte B0 = 0x01;

            public static readonly byte[] ByteMask=new byte[]{B7,B6,B5,B4,B3,B2,B1,B0};

            public static bool BitCheck(byte source, byte mask)
            {
                return (source & mask) > 0;
            }

            public static byte BitSet(byte source, byte mask, bool value)
            {
                if (value)
                {
                    return (byte)(source | mask);
                }
                else
                {
                    return (byte)(source & ~mask);
                }
                
            }

            /// <summary>
            /// extract the bits from byte
            /// example: 
            /// Value=1110 0000
            /// start=7
            /// end =5
            /// Output=0000 0111
            /// </summary>
            /// <param name="value"></param>
            /// <param name="start"></param>
            /// <param name="end"></param>
            /// <returns></returns>
            public static byte BitExtract(byte value, int start, int end)
            {
                return (byte)(value << (7-start) >> (7-(start - end)));
            }


            /// <summary>
            /// fill the target byte with spefied bits from source byte
            /// example:
            /// target = 1111 1111
            /// source = 0000 0000
            /// start = 6
            /// end = 3
            /// Output= 1100 0011
            /// </summary>
            /// <param name="target"></param>
            /// <param name="source"></param>
            /// <param name="start"></param>
            /// <param name="end"></param>
            /// <returns></returns>
            public static byte BitSet(byte target,byte source, int start,int end)
            {
                if (start<end)
                {
                    throw new ArgumentOutOfRangeException("end", "end value cannot be larget than start value");
                }
                byte mask = CreateBitMask(start, end);
                int masked_source = (source & mask); //extract the source bits
                int masked_target=(target & ~mask ); //clear the bits at target byte
                return (byte)(masked_source | masked_target);
            }

            public static byte CreateBitMask(int start, int end)
            {
                int result = 0;
                for (int i = start; i >= end; i--)
                {
                    result = result | B0<<i;
                }
                return (byte)result;
            }
        }

}
